package com.xyrl.project.common.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xyrl.common.base.exception.XyrlException;
import com.xyrl.common.util.ObjectUtil;
import com.xyrl.common.util.RedisUtil;
import com.xyrl.project.common.constant.XyrlConstant;
import com.xyrl.project.common.domian.SelectOptionVo;
import com.xyrl.project.common.system.dao.DictionaryMapper;
import com.xyrl.project.common.system.entity.Dictionary;
import com.xyrl.project.common.system.service.DictionaryService;
import com.xyrl.project.common.system.vo.DictionaryVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 数据字典管理
 *
 * @author zhongp
 */
@Service
@Slf4j
public class DictionaryServiceImpl extends ServiceImpl<DictionaryMapper, Dictionary> implements DictionaryService {

    @Override
    public void addDictionary(DictionaryVo vo) throws XyrlException {
        Dictionary dictionary = new Dictionary();
        BeanUtils.copyProperties(vo, dictionary);
        dictionary.setCreateId(vo.getUserId());
        dictionary.setCreateTime(new Date());
        try {
            this.save(dictionary);
        } catch (DuplicateKeyException e) {
            throw new XyrlException("字典key:[" + vo.getOptionKey() + "]己存在");
        }
    }

    @Override
    public boolean modieyDictionary(DictionaryVo vo) throws XyrlException {
        long total = this.baseMapper.modieyDictionary(vo);
        if (total > 0) {
            return true;
        }
        return false;
    }

    @Override
    public List<DictionaryVo> findDictionaryTree(Long id) {
        QueryWrapper wrapper = new QueryWrapper();
        if (ObjectUtil.isNotEmpty(id)) {
            wrapper.eq("parent_id", id);
        } else {
            wrapper.isNull("parent_id");
        }
        wrapper.eq("is_delete", XyrlConstant.NO);
        List<Dictionary> lists = baseMapper.selectList(wrapper);
        List<DictionaryVo> rtn = new ArrayList<>();
        for (Dictionary dic : lists) {
            DictionaryVo dictionary = new DictionaryVo();
            BeanUtils.copyProperties(dic, dictionary);
            rtn.add(dictionary);
        }
        Collections.sort(rtn);
        return rtn;
    }

    @Override
    public void delDictionary(Long id, Long userId) {
        UpdateWrapper<Dictionary> up = new UpdateWrapper<>();
        up.set("is_delete", XyrlConstant.YES);
        up.setSql("option_key=CONCAT(option_key,'_',id)");
        up.set("update_id", userId);
        up.set("update_time", new Date());
        up.eq("is_delete", XyrlConstant.NO);
        up.lambda().and(condition -> condition.eq(Dictionary::getId, id).or().eq(Dictionary::getParentId, id));
        baseMapper.update(new Dictionary(), up);
    }

    @Override
    public void delDictionary(List<String> ids, Long userId) {
        UpdateWrapper up = new UpdateWrapper<>();
        up.set("is_delete", XyrlConstant.YES);
        up.set("update_id", userId);
        up.set("update_time", new Date());
        up.in("id", ids);
        baseMapper.update(new Dictionary(), up);
    }

    @Override
    public void editDictionaryStatus(Long id, String status, Long userId) {
        UpdateWrapper up = new UpdateWrapper<>();
        up.set("status", status);
        up.set("update_id", userId);
        up.set("update_time", new Date());
        up.eq("id", id);
        baseMapper.update(new Dictionary(), up);
    }

    @Override
    public List<SelectOptionVo> findDictByKey(List<String> keys) {
        Map<Object, Object> map = RedisUtil.getMap(XyrlConstant.DICTIONARY_PREFIX);
        List<SelectOptionVo> rtnList = new ArrayList<>();
        List<String> searchKey = new ArrayList<>();
        for (String key : keys) {
            if (map.containsKey(key)) {
                rtnList.add((SelectOptionVo) map.get(key));
            } else {
                searchKey.add(key);
            }
        }

        if (ObjectUtil.isNotEmpty(searchKey)) {
            List<SelectOptionVo> searchLists = this.baseMapper.findDictByKey(searchKey);
            Map<Object, Object> cacheMaps = new HashMap<>();
            for (SelectOptionVo optionVo : searchLists) {
                cacheMaps.put(optionVo.getKey(), optionVo);
            }
            RedisUtil.setMap(XyrlConstant.DICTIONARY_PREFIX, cacheMaps);
            rtnList.addAll(searchLists);
        }
        return rtnList;
    }

    @Override
    public List<SelectOptionVo> findDictByKey(String key) {
        List<String> list = new ArrayList<>();
        list.add(key);
        return findDictByKey(list);
    }

    @Override
    public String findValueByKey(String key) {
        List<SelectOptionVo> list = findDictByKey(key);
        if (ObjectUtil.isNotEmpty(list)) {
            return list.get(0).getValue();
        }
        return "";
    }
}
